package tos

import (
	"context"
	"path/filepath"
	"strings"
	"sync"
	"tosServer/internal/pkg/common"

	"github.com/gin-gonic/gin"
	"github.com/volcengine/ve-tos-golang-sdk/v2/tos"
)

type copyParams struct {
	Ak        string `json:"ak" binding:"required"`
	Sk        string `json:"sk" binding:"required"`
	Endpoint  string `json:"endpoint" binding:"required"`
	Region    string `json:"region" binding:"required"`
	Bucket    string `json:"bucket" binding:"required"`
	Key       string `json:"key" binding:"required"`
	SrcBucket string `json:"src_bucket" binding:"required"`
	SrcKey    string `json:"src_key" binding:"required"`
}

/**
 * 复制文件
 */
func (h *Object) Copy(c *gin.Context) {
	params := &copyParams{}
	if err := c.ShouldBind(params); err != nil {
		h.Api.Error(c, &common.R{
			Msg: err.Error(),
		})
		return
	}

	credential := tos.NewStaticCredentials(params.Ak, params.Sk)
	client, err := tos.NewClientV2(params.Endpoint, tos.WithCredentials(credential), tos.WithRegion(params.Region))
	if err != nil {
		h.Api.Error(c, &common.R{
			Msg: err.Error(),
		})
		return
	}
	defer client.Close()

	copyObjectInput := &tos.CopyObjectInput{
		Bucket:    params.Bucket,
		Key:       params.Key,
		SrcBucket: params.SrcBucket,
		SrcKey:    params.SrcKey,
	}

	ext := filepath.Ext(params.Key)
	if strings.Contains(ext, "txt") {
		copyObjectInput.ContentType = "text/plain"
	}

	output, err := client.CopyObject(context.Background(), copyObjectInput)

	if err != nil {
		h.Api.Error(c, &common.R{
			Data: err.Error(),
		})
	}

	h.Api.Success(c, &common.R{
		Data: output,
	})
}

type copySubParam struct {
	Bucket    string `json:"bucket" binding:"required"`
	Key       string `json:"key" binding:"required"`
	SrcBucket string `json:"src_bucket" binding:"required"`
	SrcKey    string `json:"src_key" binding:"required"`
}

type batchCopyParams struct {
	Ak       string         `json:"ak" binding:"required"`
	Sk       string         `json:"sk" binding:"required"`
	Endpoint string         `json:"endpoint" binding:"required"`
	Region   string         `json:"region" binding:"required"`
	Batch    []copySubParam `json:"batch" binding:"required"`
}

type copyResult struct {
	Result any   `json:"result"`
	Err    error `json:"error"`
}

/**
 * 批量复制文件
 */
func (h *Object) BatchCopy(c *gin.Context) {
	params := &batchCopyParams{}
	if err := c.ShouldBind(params); err != nil {
		h.Api.Error(c, &common.R{
			Msg: err.Error(),
		})
		return
	}

	credential := tos.NewStaticCredentials(params.Ak, params.Sk)
	client, err := tos.NewClientV2(params.Endpoint, tos.WithCredentials(credential), tos.WithRegion(params.Region))
	if err != nil {
		h.Api.Error(c, &common.R{
			Msg: err.Error(),
		})
		return
	}
	defer client.Close()

	maxConcurrent := 100
	if maxConcurrent > len(params.Batch) {
		maxConcurrent = len(params.Batch)
	}

	taskCh := make(chan copySubParam, len(params.Batch))
	results := make(map[string]any)
	var wg sync.WaitGroup
	var mu sync.Mutex

	for i := 0; i < maxConcurrent; i++ {
		go func() {
			for task := range taskCh {
				copyObjectInput := &tos.CopyObjectInput{
					Bucket:    task.Bucket,
					Key:       task.Key,
					SrcBucket: task.SrcBucket,
					SrcKey:    task.SrcKey,
				}

				ext := filepath.Ext(task.Key)
				if strings.Contains(ext, "txt") {
					copyObjectInput.ContentType = "text/plain"
				}

				output, err := client.CopyObject(context.Background(), copyObjectInput)
				mu.Lock()
				results[task.SrcKey] = copyResult{
					Result: output,
					Err:    err,
				}
				mu.Unlock()
				wg.Done()
			}
		}()
	}

	for _, task := range params.Batch {
		wg.Add(1)
		taskCh <- task
	}

	close(taskCh)
	wg.Wait()

	h.Api.Success(c, &common.R{
		Data: results,
	})
}
